﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using ConfApp.Infrastructure;
using ConfApp.Services;
using Microsoft.Phone.Reactive;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Interactivity.InteractionRequest;
using Notification = Microsoft.Practices.Prism.Interactivity.InteractionRequest.Notification;

namespace ConfApp.ViewModels
{
    public class AppSettingsViewModel : ViewModel
    {
        private readonly IRegistrationServiceClient registrationServiceClient;
        private readonly ISettingsStore settingsStore;
        private readonly InteractionRequest<Notification> submitErrorInteractionRequest;
        private bool isSyncing;
        private bool subscribeToPushNotifications;

        public AppSettingsViewModel(ISettingsStore settingsStore, IRegistrationServiceClient registrationServiceClient, INavigationService navigationService)
            : base(navigationService)
        {
            this.settingsStore = settingsStore;
            this.registrationServiceClient = registrationServiceClient;
            this.submitErrorInteractionRequest = new InteractionRequest<Notification>();
            this.CancelCommand = new DelegateCommand(this.Cancel);

            this.SubmitCommand = new DelegateCommand(this.Submit);

            this.SubscribeToPushNotifications = settingsStore.SubscribeToPushNotifications;

            this.IsBeingActivated();
        }

        public DelegateCommand CancelCommand { get; set; }
        public DelegateCommand SubmitCommand { get; set; }

        public IInteractionRequest SubmitErrorInteractionRequest
        {
            get { return this.submitErrorInteractionRequest; }
        }

        public bool SubscribeToPushNotifications
        {
            get { return this.subscribeToPushNotifications; }
            set
            {
                this.subscribeToPushNotifications = value;
                this.RaisePropertyChanged(() => this.SubscribeToPushNotifications);
            }
        }
        
        public bool IsSyncing
        {
            get { return this.isSyncing; }
            set
            {
                this.isSyncing = value;
                this.RaisePropertyChanged(() => this.IsSyncing);
            }
        }

        public override sealed void IsBeingActivated()
        {
            var tombstonedSubscribe = Tombstoning.Load<bool?>("SettingsSubscribe");

            if (tombstonedSubscribe.HasValue)
            {
                this.SubscribeToPushNotifications = tombstonedSubscribe.Value;
            }
        }

        public override void IsBeingDeactivated()
        {
            if (this.SubscribeToPushNotifications != this.settingsStore.SubscribeToPushNotifications)
            {
                bool? saveVal = this.subscribeToPushNotifications;
                Tombstoning.Save("SettingsSubscribe", saveVal);
            }

            base.IsBeingDeactivated();
        }

        public void Cancel()
        {
            this.NavigationService.GoBack();
        }

        public void Submit()
        {
            this.IsSyncing = true;

            if (this.SubscribeToPushNotifications == this.settingsStore.SubscribeToPushNotifications)
            {
                this.IsSyncing = false;
                this.NavigationService.GoBack();
                return;
            }

            ObservableExtensions.Subscribe(Observable.ObserveOnDispatcher(this.registrationServiceClient
                                                                              .UpdateReceiveNotifications(this.SubscribeToPushNotifications)), taskSummary =>
                                                                              {
                                                                                  if (taskSummary ==
                                                                                      TaskSummaryResult.Success)
                                                                                  {
                                                                                      this.settingsStore.
                                                                                          SubscribeToPushNotifications
                                                                                          =
                                                                                          this.
                                                                                              SubscribeToPushNotifications;
                                                                                      this.IsSyncing = false;
                                                                                      this.NavigationService.GoBack();
                                                                                  }
                                                                                  else
                                                                                  {
                                                                                      var errorText =
                                                                                          TaskCompletedSummaryStrings
                                                                                              .
                                                                                              GetDescriptionForResult
                                                                                              (taskSummary);
                                                                                      this.IsSyncing = false;
                                                                                      this.
                                                                                          submitErrorInteractionRequest
                                                                                          .Raise(
                                                                                              new Notification
                                                                                              {
                                                                                                  Title =
                                                                                                      "Greška u komunikaciji",
                                                                                                  Content =
                                                                                                      errorText
                                                                                              },
                                                                                              n => { });
                                                                                  }
                                                                              },
                                           exception =>
                                           {
                                               if (exception is WebException)
                                               {
                                                   var webException = exception as WebException;
                                                   var summary = ExceptionHandling.GetSummaryFromWebException("Update notifications", webException);
                                                   var errorText = TaskCompletedSummaryStrings.GetDescriptionForResult(summary.Result);
                                                   this.IsSyncing = false;
                                                   this.submitErrorInteractionRequest.Raise(
                                                       new Notification { Title = "Greška u komunikaciji", Content = errorText },
                                                       n => { });
                                               }
                                               else
                                               {
                                                   throw exception;
                                               }
                                           });
        }
    }
}
